﻿#pragma once

#include "../time/local_system_time.hh"
#include "../util/object_pool.hh"
#include "../util/time_system.hh"
#include <memory>

namespace kratos {
namespace time {

class LocalDateImpl : public LocalDate {
  unique_pool_ptr<time_system::Datetime> datetime_{nullptr};

public:
  /**
   * 构造.
   *
   */
  LocalDateImpl();
  /**
   * 析构.
   *
   */
  virtual ~LocalDateImpl();
  virtual int year() const override;
  virtual int month() const override;
  virtual int day() const override;
  virtual WeekdayEnum weekday() const override;
  virtual int hour() const override;
  virtual int minute() const override;
  virtual int second() const override;
  virtual std::time_t elapsed_seconds() const override;
  virtual int elapsed_days() const override;
  virtual std::string to_string() const override;
  virtual WeekdayEnum next_weekday() const override;
  virtual WeekdayEnum prev_weekday() const override;
  virtual int days_at_week() const override;
  virtual int days_at_month() const override;
  virtual int days_at_year() const override;
  virtual int days_of_month() const override;
  virtual int days_of_year() const override;
  virtual bool is_last_day_of_week() const override;
  virtual bool is_last_day_of_month() const override;
  virtual bool is_last_day_of_year() const override;

public:
  /**
   * 根据秒时间戳设置日期.
   *
   * \param t 时间戳，秒
   * \return true或false
   */
  virtual bool from(std::time_t t) noexcept;
  /**
   * 根据字符串时间戳设置日期
   *
   * \param fmt 字符串描述的日期，根式为：%d/%d/%d %d:%d:%d
   * \return true或false
   */
  virtual bool from(const std::string &fmt) noexcept;
};

class LocalTimeImpl : public LocalTime {
public:
  LocalTimeImpl();
  /**
   * 析构.
   *
   */
  virtual ~LocalTimeImpl();
  /**
   * 获取本地时间戳，毫秒.
   *
   * \return 本地时间戳，毫秒
   */
  virtual std::time_t get_millionsecond() noexcept override;
  /**
   * 获取本地时间戳，秒.
   *
   * \return 本地时间戳，秒
   */
  virtual std::time_t get_second() noexcept override;
  /**
   * 获取与UTC时间的差，秒.
   *
   * \return 与UTC时间的差，秒
   */
  virtual std::time_t utc_diff_second() noexcept override;
  /**
   * 获取当前时间与时间戳t相差的天数，时间戳单位为秒.
   *
   * \param t 时间戳，秒
   * \return 天数差
   */
  virtual int diff_days(std::time_t t) noexcept override;
  /**
   * 获取时间戳t1与时间戳t2相差的天数，时间戳单位为秒.
   *
   * \param t1 时间戳，秒
   * \param t2 时间戳，秒
   * \return 天数差
   */
  virtual int diff_days(std::time_t t1, std::time_t t2) noexcept override;
  /**
   * 获取当前日期的.
   *
   * \return 当前日期
   */
  virtual std::unique_ptr<LocalDate> get_date() noexcept override;
  /**
   * 根据日期字符串获取日期.
   *
   * \param fmt 日期字符串
   * \return 日期
   */
  virtual std::unique_ptr<LocalDate>
  from(const std::string &fmt) noexcept override;
  /**
   * 根据时间戳(秒)获取日期.
   *
   * \param t 时间戳(秒)
   * \return 日期
   */
  virtual std::unique_ptr<LocalDate> from(std::time_t t) noexcept override;
  /**
   * 检测两个时间戳是否是同一天.
   *
   * \param t1 时间戳(秒)
   * \param t2 时间戳(秒)
   * \return true或false
   */
  virtual bool in_same_day(std::time_t t1, std::time_t t2) noexcept override;
  /**
   * 检测两个时间戳是否是同一周.
   *
   * \param t1 时间戳(秒)
   * \param t2 时间戳(秒)
   * \return true或false
   */
  virtual bool in_same_week(std::time_t t1, std::time_t t2) noexcept override;
  /**
   * 检测两个时间戳是否是同一月.
   *
   * \param t1 时间戳(秒)
   * \param t2 时间戳(秒)
   * \return true或false
   */
  virtual bool in_same_month(std::time_t t1, std::time_t t2) noexcept override;
};

} // namespace time
} // namespace kratos
